# encoding:utf-8
import json
import pickle
import traceback
import logging
from datetime import datetime, timedelta
from io import BytesIO
import random

from werkzeug.security import generate_password_hash, check_password_hash
from flask import Blueprint, request, g, make_response
from flask_restful import Resource, Api, reqparse, marshal, fields, current_app

from common.model_fields.user import user_fields
from common.model_fields.video import video_fields
from common.utils.custom_output_json import custom_output_json
from common.utils.jwt_util import _generate_token, refresh_token, generate_jwt
from common.models import db
from common.models.user import UserBase
from common.models.video import Video
from common.utils.utils import generate_code, random_string_generator
from common.utils.login_util import check_code


user_bp = Blueprint('user_bp', __name__, url_prefix='/user')
api = Api(user_bp)


@api.representation('application/json')
def output_json(data, code=200, headers=None):
    return custom_output_json(data, code, headers)


class AuthorizationResource(Resource):
    """
    注册账号
    """

    def post(self):
        try:
            parser = reqparse.RequestParser()
            args_list = ['account', 'password']
            for args in args_list:
                parser.add_argument(args, required=True)
            args = parser.parse_args()
            account = args.get('account')
            password = args.get('password')

            if not all([account, password]):
                return {'message': 'params is error', 'code': 400}

            # 验证用户是否已经注册
            user = UserBase.query.filter_by(account=account).first()
            if user:
                return {'code': 405, 'result': '该用户已存在'}

            # 通过验证，注册用户
            password = generate_password_hash(password)
            user = UserBase(account=account, password=password)
            user.last_login = datetime.now()
            user.appkey_id = random_string_generator(20)
            user.secret = random_string_generator(20)
            db.session.add(user)
            db.session.commit()
            return marshal(user, user_fields)
        except:
            error = traceback.format_exc()
            logging.error('register_user error:{}'.format(error))
            return {'error': error, 'code': 500}


class Login(Resource):
    """
    登录
    增加验证码验证
    """

    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument('account')
        parser.add_argument('password')
        args = parser.parse_args()
        account = args.get('account')
        password = args.get('password')

        # 判断用户账号密码是否正确
        user = UserBase.query.filter_by(account=account).first()
        if not user:
            return {'message': '账号不存在'}, 405
        check_password = check_password_hash(user.password, password)
        if not check_password:
            return {'code': 406, 'message': '用户名或密码错误'}
        # 最后一次登录时间
        user.last_login = datetime.now()
        user_id = user.id
        db.session.commit()
        # 生成token
        token, refresh_token = _generate_token(account, user_id)
        return {'token': token, 'refresh_token': refresh_token, 'account': account,
                'secret': user.secret, 'uid': user_id, 'appkey_id': user.appkey_id}


class VerificationCode(Resource):
    """
    图片验证码
    """

    def get(self):
        try:
            parser = reqparse.RequestParser()
            parser.add_argument('uuid')
            args = parser.parse_args()
            uuid = args.get('uuid')

            # 生成图片验证码
            text, image = generate_code()
            # 保存验证码到redis
            rds.setex(uuid, 60 * 5, text)

            out = BytesIO()
            image.save(out, 'png')
            out.seek(0)
            resp = make_response(out.read())
            resp.content_type = 'image/png'
            return resp
        except:
            error = traceback.format_exc()
            logging.error('code image error{}'.format(error))
            return 'fail'


class GetUserInfo(Resource):
    """
    获取用户基本信息
    """

    def get(self):
        parser = reqparse.RequestParser()
        parser.add_argument('account')
        parser.add_argument('password')
        args = parser.parse_args()
        account = args.get('account')
        password = args.get('password')
        user = UserBase.query.filter_by(account=account).first()
        if not user:
            return {'message': '账号'}, 400
        if not check_password_hash(user.password, password):
            return {'message': '密码错误'}, 401
        video_list = Video.query.filter_by(user=user.id).all()
        result = {
            'account': user.account,
            'videos': marshal(video_list, video_fields)
        }
        return result


class GetUploadToken(Resource):
    """
    获取上传数据所需的token

    返回一个1小时token
    """
    def get(self):
        parser = reqparse.RequestParser()
        parser.add_argument('appkey_id')
        args = parser.parse_args()
        appkey_id = args.get('appkey_id')

        secret = current_app.config.get('JWT_SECRET')
        # 定义过期时间
        expiry = datetime.utcnow() + timedelta(minutes=10)
        # 生成Token
        token = generate_jwt({'appkey_id': appkey_id}, expiry, secret)
        return {'token': token}


api.add_resource(AuthorizationResource, '/register_user', endpoint='user/register_user')
api.add_resource(Login, '/login', endpoint='/login')
api.add_resource(GetUserInfo, '/get_user', endpoint='get_user')
api.add_resource(GetUploadToken, '/get_token', endpoint='get_token')
